/*业务逻辑
在聊天用户表中转发消息
转发需要把服务器收到的消息转发到每一个用户的套接字上
每一次转发需要遍历用户列表，是一个循环，使用线程池完成这个循环 */
#include<vector>
#include<functional>
#include"PthreadPool.hpp"
#include"InetAddr.hpp"
#include"Log.hpp"
#include"LockGuard.hpp"

using task_t = std::function<void()>;
class Route
{
public:
    void CheckUsr(InetAddr& who)
    {
        for(auto& usr:_online_usr)
        {
            if(usr==who)
            {
                return;
            }
        }
        LOG(DEBUG, "a new usr %s into the online_list\n", who.AddrString().c_str());
        _online_usr.push_back(who);
    }
    void OFFUsr(InetAddr& who)
    {
        auto iter = _online_usr.begin();
        for (; iter != _online_usr.end();iter++)
        {
            if(*iter == who)
            {
                LOG(DEBUG, "usr %s off line\n", iter->AddrString());
                _online_usr.erase(iter);
                return;
            }
        }
    }
    void ForwardHelper(int sockfd,std::string message,InetAddr who)
    {
        LOG(DEBUG, "进行转发\n");
        LOG(DEBUG, "用户数量:%d\n",_online_usr.size());
        for (auto &usr : _online_usr)
        {
            std::string send_message = "[" + who.IP() + ":" + std::to_string(who.Port()) + "]# " + message;
            LOG(DEBUG, "%s\n", send_message.c_str());
            struct sockaddr_in usrAddr = usr.Addr();
            sendto(sockfd, send_message.c_str(), send_message.size(), 0, (struct sockaddr *)&usrAddr, sizeof(usrAddr));
        }
    }
    void Forward(int sockfd,std::string message,InetAddr who)
    {
        CheckUsr(who);
        if (message == "Q" || message == "QUIT"||message == "q" || message == "quit")
        {
            OFFUsr(who);
        }
        //传过来的是服务器的套接字，已经绑定了的
        //直接转发
        //需要不断创建函数作为任务加入任务队列
        task_t t = std::bind(&Route::ForwardHelper, this, sockfd, message, who);
        ThreadPool<task_t>::getInstance()->Equeue(t);
    }

    private:
        std::vector<InetAddr> _online_usr;
};